﻿/*
 * This file is part of SCWS.
 * SCWS is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 * 
 * Foobar is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with SCWS.  If not, see <http://www.gnu.org/licenses/>.
 */

using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Xml;
using System.Xml.Schema;
using System.Data;
using System.Globalization;
using System.Security.Principal;
using Microsoft.EnterpriseManagement;
using Microsoft.EnterpriseManagement.Configuration;
using Microsoft.EnterpriseManagement.Administration;
using Microsoft.EnterpriseManagement.Common;
using Microsoft.EnterpriseManagement.Monitoring;


namespace Scws
{
    /// <summary>
    /// Operations Manager Web Services
    /// </summary>
    [WebService(Namespace = "http://www.hardac.co.uk/webservices/scws")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
    // [System.Web.Script.Services.ScriptService]

    public partial class Om : System.Web.Services.WebService
    {



        [WebMethod]
        public DataSet MMStartByGroupName(string groupname, string rms, int minutes, string reason, string comment)
        {
            VerifyMMParams(ref minutes, ref comment);

            ManagementGroup mg = GetMG(rms);

            DataTable dt = QueryMonitoringObjectsByClassName(rms, groupname, "System.Group").Tables[0];

            if (dt.Rows.Count != 1)
                throw new TooManyObjectsFoundException("Too many or not enough groups found");
            
            DataRow row = dt.Rows[0];
            MonitoringObjectGenericCriteria criteria = new MonitoringObjectGenericCriteria("Id = '" + row["Id"].ToString() + "'");
            ReadOnlyCollection<PartialMonitoringObject> group = mg.GetPartialMonitoringObjects(criteria);
            //ReadOnlyCollection<PartialMonitoringObject> members = GetGroupMembers(row["Id"].ToString(), rms);

            DateTime mmstart = DateTime.Now.ToUniversalTime();

            DateTime mmstop = DateTime.Now.AddMinutes(minutes).ToUniversalTime();

            MaintenanceModeReason mmr = GetMMReason(reason);

            TraversalDepth td = TraversalDepth.Recursive;

            DataSet results = GetMMResultsDataSet();

            return ScheduleMM(rms, group, mmstart, mmstop, mmr, td, comment, ref results);

        }


        [WebMethod]
        public DataSet MMStartByMonitoringObjectId(string monitoringobjectid, string rms, int minutes, string reason, string comment, bool recursive)
        {

            VerifyMMParams(ref minutes, ref comment);

            ManagementGroup mg = GetMG(rms);

            MonitoringObjectGenericCriteria criteria = new MonitoringObjectGenericCriteria("Id = '" + monitoringobjectid + "'");

            ReadOnlyCollection<PartialMonitoringObject> objects = mg.GetPartialMonitoringObjects(criteria);

            MaintenanceModeReason mmr = GetMMReason(reason);

            TraversalDepth td;

            if (recursive == true)
            {
                td = TraversalDepth.Recursive;
            }
            else
            {
                td = TraversalDepth.OneLevel;
            }

            DateTime mmstart = DateTime.Now.ToUniversalTime();

            DateTime mmstop = mmstart.AddMinutes(minutes).ToUniversalTime();
            
            DataSet results = GetMMResultsDataSet();

            return ScheduleMM(rms, objects, mmstart, mmstop, mmr, td, comment, ref results);

        }



        /// <summary>
        /// Starts MM when supplied for a computername
        /// Will search for the name and place into MM if 
        /// there is only one object found
        /// </summary>
        /// <param name="windowscomputername">string</param>
        /// <param name="rms">string</param>
        /// <param name="minutes">int</param>
        /// <param name="reason">mmreason</param>
        /// <param name="comment">mmcomment</param>
        /// <returns>datatable</returns>
        [WebMethod]
        public DataSet MMStartByWindowsComputerName(string windowsComputerName, string rms, int minutes, string reason, string comment)
        {
            VerifyMMParams(ref minutes, ref comment);

            string monitoringobjectid = GetMonitoringObjectId(rms, windowsComputerName, "Microsoft.Windows.Computer");

            return MMStartByMonitoringObjectId(monitoringobjectid, rms, minutes, reason, comment, true);
        }



        [WebMethod]
        public DataSet MMStopByMonitoringObjectId(string monitoringobjectid, string rms, bool recursive)
        {

            Guid g = new Guid(monitoringobjectid);

            ManagementGroup mg = GetMG(rms);

            PartialMonitoringObject monobj = mg.GetPartialMonitoringObject(g);

            TraversalDepth td = TraversalDepth.OneLevel;

            if (recursive == true)
            {
                td = TraversalDepth.Recursive;
            }

//            Collection<MaintenanceWindow> objects = new Collection<MaintenanceWindow>();

            DataSet results = GetMMResultsDataSet();

            if (!monobj.InMaintenanceMode)
            {
                AddMMResultRow(ref results, monobj, "notinmm");
            }
            else
            {
                monobj.StopMaintenanceMode(DateTime.Now.ToUniversalTime(), td);
                AddMMResultRow(ref results, monobj, "removed");
            }

            return results;

        }


        [WebMethod]
        public DataSet MMStopByWindowsComputerName(string windowscomputername, string rms)
        {
            string monitoringobjectid = GetMonitoringObjectId(rms, windowscomputername, "Microsoft.Windows.Computer");

            //DataSet results = GetMMResultsDataSet();

            return MMStopByMonitoringObjectId(monitoringobjectid, rms, true);
        }


        [WebMethod]
        public DataSet MMStopByGroupName(string groupName, string rms)
        {
            string monitoringobjectid = GetMonitoringObjectId(rms, groupName, "System.Group");

            //DataSet results = GetMMResultsDataSet();

            return MMStopByMonitoringObjectId(monitoringobjectid, rms, true);
        }


        [WebMethod]
        public string GetMonitoringObjectId(string rms, string query, string classname)
        {
            DataTable dt = QueryMonitoringObjectsByClassName(rms, query, classname).Tables[0];

            if (dt.Rows.Count != 1)
                throw new Om.TooManyObjectsFoundException("Too many or not enough objects found: " + dt.Rows.Count.ToString());

            DataRow row = dt.Rows[0];

            return row["Id"].ToString();

        }



        /// <summary>
        /// returns a data tableof all objects in MM
        /// </summary>
        /// <param name="rms"></param>
        /// <returns></returns>
        [WebMethod]
        public DataSet GetObjectsInMM(string rms)
        {
            ManagementGroup mg = GetMG(rms);

            ReadOnlyCollection<PartialMonitoringObject> objects;

            MonitoringObjectGenericCriteria criteria = new MonitoringObjectGenericCriteria("InMaintenanceMode=1");

            objects = mg.GetPartialMonitoringObjects(criteria);

            return OutPartialMonitoringObject(objects);
        }


        /// <summary>
        /// This method returns useful information on a monitoringobject when supplied
        /// with the monitoringobject ID as a string.
        /// </summary>
        /// <param name="rms"></param>
        /// <param name="monitoringobjectid"></param>
        /// <returns></returns>
        [WebMethod]
        public DataSet GetMonitoringObjectInfo(string rms, string monitoringobjectid)
        {
            ManagementGroup mg = GetMG(rms);

            Guid g = new Guid(monitoringobjectid);

            MonitoringObjectGenericCriteria criteria = new MonitoringObjectGenericCriteria("Id = '" + g.ToString()+ "'");

            ReadOnlyCollection<PartialMonitoringObject> objects = mg.GetPartialMonitoringObjects(criteria);

            return OutPartialMonitoringObject(objects);
        }


        [WebMethod]
        public DataSet QueryMonitoringObjectsByClassName(string rms, string query, string objectclassname)
        {
            ManagementGroup mg = GetMG(rms);

            MonitoringClass mc = GetMonitoringClass(rms, objectclassname);

            MonitoringObjectGenericCriteria criteria =
                new MonitoringObjectGenericCriteria("DisplayName LIKE '%" + query + "%' OR Path LIKE '%" + query + "%'");

            ReadOnlyCollection<PartialMonitoringObject> objects = mg.GetPartialMonitoringObjects(criteria, mc);

            return OutPartialMonitoringObject(objects);

        }


        /// <summary>
        /// Returns a string array containing valid maintenance mode reasons
        /// </summary>
        /// <returns></returns>
        [WebMethod]
        public string[] GetMMReasons()
        {
            int numberofreasons = Enum.GetValues(typeof(MaintenanceModeReason)).Length;
            int i = 0;
            string[] reasons = new string[numberofreasons];
            foreach (MaintenanceModeReason reason in Enum.GetValues(typeof(MaintenanceModeReason)))
            {
                reasons[i] = reason.ToString();
                i++;
            }
            return reasons;
        }


        /// <summary>
        /// returns an array of all monitoring classes from the RMS
        /// Does not include singleton classes
        /// </summary>
        /// <param name="rms"></param>
        /// <returns></returns>
        [WebMethod]
        public string[] GetAllMonitoringClasses(string rms)
        {

            //declare a management group with which to connect
            ManagementGroup mg = default(ManagementGroup);

            //connect to management group
            mg = GetMG(rms);

            //declare results varaible
            ArrayList al = new ArrayList();

            //declare a readonlycollection to store the monitoring classes from the RMS
            ReadOnlyCollection<MonitoringClass> monclasses = default(ReadOnlyCollection<MonitoringClass>);

            //get the list of monitoring classes from the rms and store in the monclasses object
            monclasses = mg.GetMonitoringClasses();

            //loop through all the classes in our collection
            foreach (var c in monclasses)
            {

                //if the class is a singleton then skip it
                //this means we do not get groups and things included in this list
                if (c.Singleton == false)
                {
                    //store the name, e.g. microsoft.windows.computer
                    al.Add(c.Name.ToString());
                }
            }

            //get the results and convert from arraylist to array
            string[] results = new string[al.Count];

            for (int i = 0; i < al.Count; i++)
            {
                results[i] = al[i].ToString();
            }

            al = null;

            //clean up

            mg = null;
            monclasses = null;

            //we're done

            return results;
        }



    }
}
